"""
拖拽双圆
在一个黑色背景的窗口中，初始放置两个白色圆。
用鼠标拖拽某个圆时，会使圆移动。
白色圆不能相交。

圆是否允许走出窗口？
被拖拽的圆是否能将静态的圆挤走？

代码说明：

​窗口初始化​：创建800x600的黑色背景窗口，初始化两个白色圆形
​绘制逻辑​：在on_draw方法中使用arcade.draw_circle_filled绘制圆形
​鼠标交互​：
按下时检测是否点击在圆形范围内
拖拽时更新圆形位置
释放时取消选中状态
​碰撞处理​：
计算两个圆心之间的欧氏距离
当距离小于两圆半径之和时，调整被拖拽圆形的位置
使用向量缩放算法保持圆形刚好接触的状态
运行效果：

两个白色圆形可以在窗口中自由拖拽
当试图让两个圆形重叠时，会被自动推开保持接触但不重叠的状态
支持同时拖拽任意一个圆形（但一次只能拖拽一个）
这个实现使用了基础的几何计算来处理碰撞，确保圆形始终保持最小安全距离。您可以通过修改初始坐标和半径参数来调整圆形的初始位置和大小。

"""
from __future__ import annotations

import math

import arcade


class DraggableCircles(arcade.Window):
    def __init__(self):
        super().__init__(width=800, height=600, title="Drag Circles")
        arcade.set_background_color(arcade.color.BLACK)
        
        # 初始化两个圆形，设置初始位置和半径
        self.circles = [
            {'x': 200, 'y': 300, 'radius': 30, 'dragging': False},
            {'x': 600, 'y': 300, 'radius': 30, 'dragging': False}
        ]

    def on_draw(self):
        """ 绘制窗口内容 """
        """
        在arcade 2.x及更早版本中，arcade.start_render()会自动清除窗口并用背景色填充
        从arcade 3.0版本开始，start_render()不再自动清除窗口，需要显式调用clear()
        """
        # arcade.start_render()
        self.clear()
        for circle in self.circles:
            arcade.draw_circle_filled(
                circle['x'], circle['y'], circle['radius'], arcade.color.WHITE
            )

    def on_mouse_press(self, x: int, y: int, button: int, modifiers: int):
        """ 鼠标按下时检测是否选中圆形 """
        for circle in self.circles:
            dx = x - circle['x']
            dy = y - circle['y']
            if math.sqrt(dx**2 + dy**2) <= circle['radius']:
                circle['dragging'] = True

    def on_mouse_release(self, x: int, y: int, button: int, modifiers: int):
        """ 鼠标释放时取消选中 """
        for circle in self.circles:
            circle['dragging'] = False

    def on_mouse_drag(self, x: int, y: int, dx: int, dy: int, buttons: int, modifiers: int):
        """ 鼠标拖拽时移动圆形并处理碰撞 """
        for circle in self.circles:
            if not circle['dragging']:
                continue
            
            # 更新为当前鼠标位置
            circle['x'] = x
            circle['y'] = y
            
            # 检查与其他圆形的碰撞
            for other in self.circles:
                if other is circle:
                    continue
                
                # 计算圆心间距
                dx_c = circle['x'] - other['x']
                dy_c = circle['y'] - other['y']
                distance = math.sqrt(dx_c**2 + dy_c**2)
                min_distance = circle['radius'] + other['radius']
                
                # 处理碰撞
                if distance < min_distance:
                    if distance == 0:  # 处理完全重叠的特殊情况
                        circle['x'] += min_distance
                    else:
                        # 将圆形调整到刚好接触的位置
                        scale = min_distance / distance
                        circle['x'] = other['x'] + dx_c * scale
                        circle['y'] = other['y'] + dy_c * scale

def main():
    window = DraggableCircles()
    arcade.run()

if __name__ == "__main__":
    main()